每天的專案會同步到 GitLab 上,可以前往 GitLab 查看。
有興趣的朋友歡迎留言 or 來信討論,我的信箱是 nickchen1998@gmail.com。
昨天介紹了如何客製化一個自己的 Tool,今天我們來看一下 LangChain 內建的 Tool,
如同標題所述,今天我們挑選的 Tool 就是 QuerySQLDataBaseTool
,這個 Tool 可以協助我們針對資料庫進行一些操作。
首先我們要先建立一個資料表,這邊我們使用 SQLite 作為範例,並且建立兩張資料表,分別是 Items 以及 Orders:
下方的程式碼是使用 SQLAlchemy 2.0 來進行開發的,針對這點不熟的朋友,可以參考 官方文件 來了解如何使用 SQLAlchemy 2.0。
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
Base = declarative_base()
class Order(Base):
__tablename__ = 'orders'
id = Column(Integer, primary_key=True, index=True)
customer_name = Column(String, index=True)
items = relationship("Item", back_populates="order")
class Item(Base):
__tablename__ = 'items'
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True)
quantity = Column(Integer)
order_id = Column(Integer, ForeignKey('orders.id'))
order = relationship("Order", back_populates="items")
def main():
engine = create_engine("sqlite:///./test.db", echo=True)
session = sessionmaker(autocommit=False, autoflush=False, bind=engine)()
Base.metadata.drop_all(bind=engine)
Base.metadata.create_all(bind=engine)
order1 = Order(customer_name="Alice")
order1.items = [
Item(name="Latte", quantity=1),
Item(name="Cappuccino", quantity=2)
]
order2 = Order(customer_name="Bob")
order2.items = [
Item(name="Espresso", quantity=1),
Item(name="Mocha", quantity=1)
]
session.add_all([order1, order2])
session.commit()
session.close()
if __name__ == "__main__":
main()
直接執行上面這段程式碼,應該可以看到你的目錄當中出現了一個 test.db
這個 sqlite 資料庫檔,
並且裡面會有如下圖中的兩張資料表以及一些資料。
我們可以透過 QuerySQLDataBaseTool
來進行資料庫的操作,這個 Tool 會將 SQL 語句傳遞給資料庫進行操作,
這個物件當中需要接收一個名為 db
的參數,型態為 SQLDatabase,這個參數是用來設定你要連到哪個資料庫,可以參考下方的範例:
from env_settings import EnvSettings
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from langchain_community.tools import QuerySQLDataBaseTool
from langchain_community.utilities import SQLDatabase
env_settings = EnvSettings()
llm = ChatOpenAI(
api_key=env_settings.OPENAI_API_KEY,
model_name="gpt-4o"
)
db = SQLDatabase.from_uri("sqlite:///./test.db")
tools = [QuerySQLDataBaseTool(db=db)]
llm = llm.bind_tools(tools)
messages = [HumanMessage(content="請問現在有幾張訂單?")]
ai_message = llm.invoke(messages)
print(ai_message.tool_calls)
可以看到在範例當中,我們將 QuerySQLDataBaseTool
這個 Tool 傳入 tools
這個列表當中,並且透過 SQLDatabase 來設定我們要連接的資料庫,
下圖中可以看到 GPT 成功針對我們的問題選擇了指定的 Tool 並且產生了指定的 SQL 語句:
在確認他可以自動讀取到我們的資料表並產生 SQL 語句後,我們就趕緊把這個 Tool 的流程串起來,下方是完整的程式碼:
from env_settings import EnvSettings
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, ToolMessage
from langchain_community.tools import QuerySQLDataBaseTool
from langchain_community.utilities import SQLDatabase
env_settings = EnvSettings()
llm = ChatOpenAI(
api_key=env_settings.OPENAI_API_KEY,
model_name="gpt-4o"
)
db = SQLDatabase.from_uri("sqlite:///./test.db")
tools = [QuerySQLDataBaseTool(db=db)]
llm = llm.bind_tools(tools)
messages = [HumanMessage(content="請問現在有幾張訂單?")]
ai_message = llm.invoke(messages)
tool_messages = []
for tool_call in ai_message.tool_calls:
for tool in tools:
if tool_call.get("name") == tool.name:
tool_content = tool.run(tool_call.get("args"))
print(f"tool content: {tool_content}")
tool_messages.append(ToolMessage(
content=tool_content,
tool_call_id=tool_call.get("id"),
))
break
messages.append(ai_message)
messages.extend(tool_messages)
ai_message = llm.invoke(messages)
print(f"ai content: {ai_message.content}")
在範例中可以看到,我們把 tool content 以及 ai content 印出來(如下圖),方便我們查看查詢出的資料是否正確以及回答的內容,可以看到查出來以及
GPT 的回答都是正確的。
今天我們介紹了該如何使用 QuerySQLDataBaseTool
這個 Tool 來進行資料庫的操作,然而應該有朋友會發現,當你的資料表更加複雜時,
會慢慢地出現錯誤的 SQL 語句,如下圖中我們把問題換成複雜一點,可以看到他產生了跟我們設計的資料表不符的 SQL 語法
那是因為 QuerySQLDataBaseTool
其實本質上只是個用來 執行 SQL 的一個 Tool,
明天我們將要介紹一下在 LangChain 當中獨特的鍊式語言 Chain,將資料表資訊整合進整個查詢的過程當中。